<?php
/**
 * Copyright (c) 2006-2008, Julien PORTALIER
 * http://featherphp.googlecode.com/
 * 
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 */

/**
 * Handles member authentification.
 */
class AuthComponent
{
	private $controller;
	private $Session;
	private $attributes = array(
		'id'         => 'Anonymous',
		'member'     => null,
		'groups'     => array(),
		'identified' => false,
	);
	
	/**
	 * Automatically signs user in at load time.
	 * 
	 * @param $controller Controller
	 */
	function startup(Controller $controller)
	{
		$this->controller = $controller;
		$this->Session    = $controller->Session;
		
#		debug($_SESSION);
		
		if (isset($_SESSION['Member']))
		{
			# already logged in
			$this->sign_in($_SESSION['Member'], false);
		}
		elseif (Cookies::check(Core::long_session_cookie))
		{
			# automatic login by long session id (silences any error)
			try
			{
				# login is done on main site
				if ($_SERVER['HTTP_HOST'] != FULL_DOMAIN)
				{
					$here = PROTOCOL.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
					HTTP::redirect(MAIN_SITE_URL.'/members/auto_login?redirect='.urlencode($here));
				}
				
				# we are on the main site
				$long_session_id = Cookies::read(Core::long_session_cookie);
				if (!empty($long_session_id))
				{
					$Member = Load::new_model('Member');
					$Member->long_session_login($long_session_id);
					
					$this->sign_in($Member);
					$this->set_long_session($long_session_id);
					return;
				}
			}
			catch(Exception $e)
			{
			}
			$this->set_long_session(0);
		}
	}
	
	/**
	 * Attributes are read only, thus we allow direct read.
	 */
	function __get($attr)
	{
		if (isset($this->attributes[$attr])) {
			return $this->attributes[$attr];
		}
	}
	
	/**
	 * Attributes are read only, thus we forbid external direct write.
	 */
	private function __set($attr, $value)
	{
		$this->attributes[$attr] = $value;
	}
	
	/**
	 * Signs a member in.
	 * 
	 * @param $member Mixed Array or Member Object.
	 * @param $set_session Boolean Set $_SESSION['Member'] or not.
	 */
	function sign_in($member, $set_session=true)
	{
		if ($member instanceof Object)
		{
			$_member = array();
			foreach($member as $k => $v) {
				$_member[$k] = $v;
			}
			$this->member = $_member;
		}
		elseif (empty($member))
		{
			#$this->sign_out();
			return;
		}
		else
		{
			$this->member = $member;
		}
		
		$this->id = $this->member['id'];
		$this->identified = true;
		
		$this->groups = empty($this->member['groups']) ?
			array('member') : $this->member['groups'];
		
		if ($set_session)
		{
			if (!Core::session_auto) {
				$this->Session->start();
			}
			$_SESSION['Member'] = $this->member;
		}
	}
	
	/**
	 * Signs current member out.
	 */
	function sign_out()
	{
		$this->id         = 'Anonymous';
		$this->identified = false;
		$this->member     = array();
		$this->groups     = array();
		$this->Session->destroy();
		$this->set_long_session(0);
	}
	
	/**
	 * Sets or removes the cookie for automatic login.
	 * 
	 * @param $long_session_id String
	 */
	function set_long_session($long_session_id=0)
	{
		if ($long_session_id) {
			Cookies::write(Core::long_session_cookie, $long_session_id, Core::long_session_expire);
		}
		else {
			Cookies::delete(Core::long_session_cookie);
		}
	}
	
	/**
	 * Stores or retrieves informations about an anonymous user.
	 * 
	 * Store:    Auth::remember_anonymous($data);
	 * Retrieve: $data = Auth::remember_anonymous();
	 * Delete:   Auth::remember_anonymous(false);
	 * 
	 * @return Array Stored data.
	 * @param $data Mixed[Optional] Required in write mode.
	 */
	function & remember_anonymous($data=null)
	{
		if ($data === false) {
			Cookies::delete('remember_anonymous');
		}
		elseif (empty($data)) {
			$data = Cookies::check('remember_anonymous') ? Cookies::read('remember_anonymous') : array();
		}
		else {
			Cookies::write('remember_anonymous', &$data);
		}
		return $data;
	}
	
	/**
	 * Is current user member of any of these groups?
	 * 
	 * @param $groups Mixed A collection of groups.
	 */
	function in_group($groups)
	{
		$groups = array_collection($groups);
		$groups = array_intersect($this->attributes['groups'], $groups);
		return !empty($groups);
	}
	
	/**
	 * If an access is forbidden, either redirects the anonymous user
	 * to the login page, or displays an explaination message.
	 * 
	 * @param $mesg String[optional]
	 * @param $url  String[optional]
	 */
	function forbidden($mesg=null, $url=null)
	{
		if (!$this->identified)
		{
			$url = urlencode(empty($url) ? HTTP::$referer : $url);
			$this->controller->flash(t('Access forbidden, please login.'),
				(defined('MAIN_SITE_URL') ? MAIN_SITE_URL : '')."/members/login?referer=$url", 'notice', 401);
		}
		else
		{
			if (empty($mesg)) {
				$mesg = t('Access forbidden.');
			}
			$this->controller->flash($mesg, "/", 'error', 403);
		}
	}
}
?>